package com.portal.base.authenticate.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.portal.base.authenticate.entity.SysPermission;
import com.portal.base.authenticate.mapper.SysPermissionMapper;
import com.portal.base.authenticate.service.AbstractUserPermission;
import com.portal.base.authenticate.util.JwtUtil;
import com.portal.base.core.constant.CacheConstant;
import com.portal.base.core.constant.CommonConstant;
import com.portal.base.core.util.PasswordUtil;
import com.portal.base.core.util.RedisUtil;
import com.portal.base.core.util.oConvertUtils;
import com.portal.base.core.vo.DefContants;
import com.portal.base.core.vo.Result;
import com.portal.base.org.entity.SysDepart;
import com.portal.base.org.service.ISysDepartService;
import com.portal.base.user.entity.SysUser;
import com.portal.base.user.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @program: tpg-portal-parent
 * @description:  用户权限相关操作。
 * @author: xuduo
 * @create: 2020-05-11 10:24
 * @Version: 1.0
 **/
@Service
@Slf4j
public class UserPermissionImpl implements AbstractUserPermission {

    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysDepartService sysDepartService;


    /**
     * 通过用户名获取用户权限集合
     *
     * @param username 用户名
     * @return 权限集合
     */
    @Override
    public Set<String> getUserPermissionsSet(String username) {
        Set<String> permissionSet = new HashSet<>();
        List<SysPermission> permissionList = sysPermissionMapper.queryByUser(username);
        for (SysPermission po : permissionList) {
//			// TODO URL规则有问题？
//			if (oConvertUtils.isNotEmpty(po.getUrl())) {
//				permissionSet.add(po.getUrl());
//			}
            if (oConvertUtils.isNotEmpty(po.getPerms())) {
                permissionSet.add(po.getPerms());
            }
        }
        log.info("-------通过数据库读取用户拥有的权限Perms------username： "+ username+",Perms size: "+ (permissionSet==null?0:permissionSet.size()) );
        return permissionSet;
    }

    /**
     * 用户登陆系统并办法token
     * @param username 用户名
     * @param password 密码
     * @return
     */
    public Result<JSONObject> userLogin(String username,String password){

        Result<JSONObject> result = new Result<JSONObject>();
//1. 校验用户是否有效
        SysUser sysUser = sysUserService.getUserByName(username);
        result = sysUserService.checkUserIsEffective(sysUser);
        if(!result.isSuccess()) {
            return result;
        }

        //2. 校验用户名或密码是否正确
        String userpassword = PasswordUtil.encrypt(username, password, sysUser.getSalt());
        String syspassword = sysUser.getPassword();
        if (!syspassword.equals(userpassword)) {
            result.error500("用户名或密码错误");
            return result;
        }

        //用户登录信息
        userInfo(sysUser, result);
        return result;
    }
    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
        String syspassword = sysUser.getPassword();
        String username = sysUser.getUsername();
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        // 设置token缓存有效时间
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME*2 / 1000);

        // 获取用户部门信息
        JSONObject obj = new JSONObject();
        List<SysDepart> departs;
        departs = sysDepartService.queryUserDeparts(sysUser.getId());
        obj.put("departs", departs);
        if (departs == null || departs.size() == 0) {
            obj.put("multi_depart", 0);
        } else if (departs.size() == 1) {
            sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            obj.put("multi_depart", 1);
        } else {
            obj.put("multi_depart", 2);
        }
        obj.put("token", token);
        obj.put("userInfo", sysUser);
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    /**
     * 用户退出
     * @param token
     * @return
     */
    public Result<Object> logout( String token) {
        if(oConvertUtils.isEmpty(token)) {
            return Result.error("退出登录失败！没有获取到token。");
        }
        String username = JwtUtil.getUsername(token);
        SysUser sysUser = sysUserService.getUserByName(username);
        if(sysUser!=null) {
            /*sysBaseAPI.addLog("用户名: "+sysUser.getRealname()+",退出成功！", CommonConstant.LOG_TYPE_1, null);
            log.info(" 用户名:  "+sysUser.getRealname()+",退出成功！ ");*/
            //清空用户登录Token缓存
            redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + token);
            //清空用户登录Shiro权限缓存
            redisUtil.del(CommonConstant.PREFIX_USER_SHIRO_CACHE + sysUser.getId());
            //清空用户的缓存信息（包括部门信息），例如sys:cache:user::<username>
            redisUtil.del(String.format("%s::%s", CacheConstant.SYS_USERS_CACHE, sysUser.getUsername()));
            //调用shiro的logout
            SecurityUtils.getSubject().logout();
            return Result.ok("退出登录成功！");
        }else {
            return Result.error("Token无效!");
        }
    }

    /**
     *  从请求中获取token,前端请求需要添加X-Access-Token头信息
     * @param request
     * @return token
     */
    public  String getToken(HttpServletRequest request){
        String token = request.getHeader(DefContants.X_ACCESS_TOKEN);
        return  token;
    }

}
